home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2002 #12
/
Amiga Plus CD - 2002 - No. 12.iso
/
Tools
/
Development
/
qstat25b
/
template.c
< prev
Wrap
C/C++ Source or Header
|
2002-11-18
|
25KB
|
1,061 lines
/*
* qstat 2.5a
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Thanks to Per Hammer for the OS/2 patches (per@mindbend.demon.co.uk)
* Thanks to John Ross Hunt for the OpenVMS Alpha patches (bigboote@ais.net)
* Thanks to Scott MacFiggen for the quicksort code (smf@webmethods.com)
*
* Inspired by QuakePing by Len Norton
*
* Copyright 1996,1997,1998,1999 by Steve Jankowski
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#ifdef __hpux
#include <sys/types.h>
#include <netinet/in.h>
#endif
#ifdef _AIX
#include <sys/types.h>
#include <netinet/in.h>
#endif
#include "qstat.h"
#ifdef _WIN32
#define strcasecmp stricmp
#define strncasecmp strnicmp
#endif
#ifdef __hpux
#define STATIC static
#else
#define STATIC
#endif
/*
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _AIX
extern unsigned int ntohl(unsigned int n);
#endif
#ifdef __cplusplus
}
#endif
*/
extern int hostname_lookup;
extern int get_player_info;
extern int get_server_rules;
extern int num_servers_total;
extern int num_servers_timed_out;
extern int num_servers_down;
extern int num_players_total;
extern int html_names;
extern int hex_player_names;
extern FILE *OF; /* output file */
static char *server_template;
static char *rule_template;
static char *header_template;
static char *trailer_template;
static char *player_template;
static void display_server_var( struct qserver *server, int var);
static void display_player_var( struct player *player, int var, struct qserver *server);
static void display_rule_var( struct rule *rule, int var, struct qserver *server);
static void display_generic_var( int var);
static int parse_var( char *varname, int *varlen);
static int read_template( char *filename, char **template_text);
static void display_string( char *str);
static int is_true( struct qserver *server, struct player *player,
struct rule *rule, char *expr);
#define VARIABLE_CHAR '$'
static char *variable_option;
static int if_skip;
static int if_level;
static int if_skip_save;
static int if_level_save;
int html_mode= 0;
int clear_newlines_mode= 0;
int rule_name_spaces= 0;
struct vardef {
char *var;
int varcode;
int options;
};
#define NO_OPTIONS 0
#define OPTIONS_OK 1
#define EXPR 2
struct vardef variable_defs[] = {
#define V_HOSTNAME 1
{"HOSTNAME", V_HOSTNAME, NO_OPTIONS },
#define V_SERVERNAME 2
{"SERVERNAME", V_SERVERNAME, NO_OPTIONS },
#define V_PING 3
{"PING", V_PING, NO_OPTIONS },
#define V_PLAYERS 4
{"PLAYERS", V_PLAYERS, NO_OPTIONS | EXPR },
#define V_MAXPLAYERS 5
{"MAXPLAYERS", V_MAXPLAYERS, NO_OPTIONS },
#define V_MAP 6
{"MAP", V_MAP, NO_OPTIONS },
#define V_GAME 7
{"GAME", V_GAME, NO_OPTIONS | EXPR },
#define V_RETRIES 8
{"RETRIES", V_RETRIES, NO_OPTIONS },
#define V_IPADDR 9
{"IPADDR", V_IPADDR, NO_OPTIONS },
#define V_PORT 10
{"PORT", V_PORT, NO_OPTIONS },
#define V_ARG 11
{"ARG", V_ARG, NO_OPTIONS },
#define V_QSTATURL 12
{"QSTATURL", V_QSTATURL, NO_OPTIONS },
#define V_QSTATVERSION 13
{"QSTATVERSION", V_QSTATVERSION, NO_OPTIONS },
#define V_QSTATAUTHOR 14
{"QSTATAUTHOR", V_QSTATAUTHOR, NO_OPTIONS },
#define V_QSTATAUTHOREMAIL 15
{"QSTATAUTHOREMAIL", V_QSTATAUTHOREMAIL, NO_OPTIONS },
#define V_TYPE 16
{"TYPE", V_TYPE, NO_OPTIONS },
#define V_RULE 17
{"RULE", V_RULE, OPTIONS_OK | EXPR },
#define V_ALLRULES 18
{"ALLRULES", V_ALLRULES, NO_OPTIONS },
#define V_PLAYERTEMPLATE 19
{"PLAYERTEMPLATE", V_PLAYERTEMPLATE, NO_OPTIONS },
#define V_PLAYERNAME 20
{"PLAYERNAME", V_PLAYERNAME, NO_OPTIONS },
#define V_FRAGS 21
{"FRAGS", V_FRAGS, NO_OPTIONS },
#define V_PLAYERPING 22
{"PLAYERPING", V_PLAYERPING, NO_OPTIONS },
#define V_CONNECTTIME 23
{"CONNECTTIME", V_CONNECTTIME, NO_OPTIONS },
#define V_SKIN 24
{"SKIN", V_SKIN, NO_OPTIONS },
#define V_SHIRTCOLOR 25
{"SHIRTCOLOR", V_SHIRTCOLOR, NO_OPTIONS },
#define V_PANTSCOLOR 26
{"PANTSCOLOR", V_PANTSCOLOR, NO_OPTIONS },
#define V_PLAYERIP 27
{"PLAYERIP", V_PLAYERIP, NO_OPTIONS },
#define V_IF 28
{"IF", V_IF, OPTIONS_OK },
#define V_ENDIF 29
{"ENDIF", V_ENDIF, NO_OPTIONS },
#define V_HTML 35
{"HTML", V_HTML, NO_OPTIONS },
#define V_FLAG 36
{"FLAG", V_FLAG, OPTIONS_OK | EXPR },
#define V_UP 37
{"UP", V_UP, NO_OPTIONS | EXPR },
#define V_DOWN 38
{"DOWN", V_DOWN, NO_OPTIONS | EXPR },
#define V_IFNOT 39
{"IFNOT", V_IFNOT, OPTIONS_OK },
#define V_TIMEOUT 40
{"TIMEOUT", V_TIMEOUT, NO_OPTIONS | EXPR },
#define V_NOW 41
{"NOW", V_NOW, NO_OPTIONS },
#define V_TOTALSERVERS 42
{"TOTALSERVERS", V_TOTALSERVERS, NO_OPTIONS },
#define V_TOTALUP 43
{"TOTALUP", V_TOTALUP, NO_OPTIONS },
#define V_TOTALNOTUP 44
{"TOTALNOTUP", V_TOTALNOTUP, NO_OPTIONS },
#define V_TOTALPLAYERS 45
{"TOTALPLAYERS", V_TOTALPLAYERS, NO_OPTIONS },
#define V_TEAMNUM 49
{"TEAMNUM", V_TEAMNUM, NO_OPTIONS },
#define V_BACKSLASH 50
{"\\", V_BACKSLASH, NO_OPTIONS },
#define V_HOSTNOTFOUND 51
{"HOSTNOTFOUND", V_HOSTNOTFOUND, NO_OPTIONS | EXPR },
#define V_MESH 52
{"MESH", V_MESH, NO_OPTIONS },
#define V_ISEMPTY 56
{"ISEMPTY", V_ISEMPTY, NO_OPTIONS | EXPR },
#define V_ISFULL 57
{"ISFULL", V_ISFULL, NO_OPTIONS | EXPR },
#define V_PACKETLOSS 58
{"PACKETLOSS", V_PACKETLOSS, NO_OPTIONS },
#define V_ISTEAM 59
{"ISTEAM", V_ISTEAM, NO_OPTIONS | EXPR },
#define V_TEAMNAME 60
{"TEAMNAME", V_TEAMNAME, NO_OPTIONS },
#define V_DEFAULTTYPE 61
{"DEFAULTTYPE", V_DEFAULTTYPE, NO_OPTIONS },
#define V_TYPESTRING 62
{"TYPESTRING", V_TYPESTRING, NO_OPTIONS },
#define V_FACE 63
{"FACE", V_FACE, NO_OPTIONS },
#define V_SOLDIEROFFORTUNE 64
{"SOLDIEROFFORTUNE", V_SOLDIEROFFORTUNE, NO_OPTIONS },
#define V_COLORNUMBERS 65
{"COLORNUMBERS", V_COLORNUMBERS, NO_OPTIONS },
#define V_COLORNAMES 66
{"COLORNAMES", V_COLORNAMES, NO_OPTIONS },
#define V_COLORRGB 67
{"COLORRGB", V_COLORRGB, NO_OPTIONS },
#define V_TIMESECONDS 68
{"TIMESECONDS", V_TIMESECONDS, NO_OPTIONS },
#define V_TIMECLOCK 69
{"TIMECLOCK", V_TIMECLOCK, NO_OPTIONS },
#define V_TIMESTOPWATCH 70
{"TIMESTOPWATCH", V_TIMESTOPWATCH, NO_OPTIONS },
#define V_NOWINT 71
{"NOWINT", V_NOWINT, NO_OPTIONS },
#define V_ISMASTER 72
{"ISMASTER", V_ISMASTER, NO_OPTIONS | EXPR },
#define V_HTMLPLAYERNAME 73
{"HTMLPLAYERNAME", V_HTMLPLAYERNAME, NO_OPTIONS },
#define V_ISBOT 74
{"ISBOT", V_ISBOT, NO_OPTIONS | EXPR },
#define V_ISALIAS 75
{"ISALIAS", V_ISALIAS, NO_OPTIONS | EXPR },
#define V_TRIBETAG 76
{"TRIBETAG", V_TRIBETAG, NO_OPTIONS | EXPR },
#define V_CLEARNEWLINES 77
{"CLEARNEWLINES", V_CLEARNEWLINES, NO_OPTIONS },
#define V_GAMETYPE 78
{"GAMETYPE", V_GAMETYPE, NO_OPTIONS },
#define V_DEATHS 79
{"DEATHS", V_DEATHS, NO_OPTIONS },
#define V_TYPEPREFIX 80
{"TYPEPREFIX", V_TYPEPREFIX, NO_OPTIONS },
#define V_RULENAMESPACES 81
{"RULENAMESPACES", V_RULENAMESPACES, NO_OPTIONS },
#define V_RULETEMPLATE 82
{"RULETEMPLATE", V_RULETEMPLATE, NO_OPTIONS },
#define V_RULENAME 83
{"RULENAME", V_RULENAME, OPTIONS_OK | EXPR },
#define V_RULEVALUE 84
{"RULEVALUE", V_RULEVALUE, OPTIONS_OK | EXPR },
};
int
read_qserver_template( char *filename)
{
return read_template( filename, &server_template);
}
int
read_rule_template( char *filename)
{
return read_template( filename, &rule_template);
}
int
read_header_template( char *filename)
{
return read_template( filename, &header_template);
}
int
read_trailer_template( char *filename)
{
return read_template( filename, &trailer_template);
}
int
read_player_template( char *filename)
{
return read_template( filename, &player_template);
}
STATIC int
read_template( char *filename, char **template_text)
{
FILE *file;
int length, rc;
file= fopen( filename, "r");
if ( file == NULL) {
perror( filename);
return -1;
}
fseek( file, 0, SEEK_END);
length= ftell( file);
fseek( file, 0, SEEK_SET);
*template_text= (char*)malloc( length+1);
rc= fread( *template_text, 1, length, file);
if ( rc == 0 && length > 0) {
perror( filename);
fclose( file);
free( *template_text);
*template_text= NULL;
return -1;
}
(*template_text)[rc]= '\0';
return 0;
}
int
have_server_template()
{
return server_template != NULL;
}
int
have_header_template()
{
return header_template != NULL;
}
int
have_trailer_template()
{
return trailer_template != NULL;
}
void
template_display_server( struct qserver *server)
{
char *t= server_template;
int var, varlen;
if_level= 0;
if_skip= 0;
for ( ; *t; t++) {
if ( *t != VARIABLE_CHAR) {
if ( ! if_skip)
putc( *t, OF);
continue;
}
var= parse_var( t, &varlen);
if ( var == -1) {
if ( ! if_skip)
putc( VARIABLE_CHAR, OF);
continue;
}
if ( var == V_BACKSLASH) {
t+= 2;
if ( *t == '\r') {
if ( *++t == '\n')
t++;
}
else if ( *t == '\n')
t++;
t--;
continue;
}
if ( (var == V_IF || var == V_IFNOT) && variable_option != NULL) {
int truth= (var==V_IF)?1:0;
if ( !if_skip && is_true( server, NULL, NULL, variable_option) == truth)
if_level++;
else
if_skip++;
}
else if ( var == V_ENDIF) {
if ( if_skip)
if_skip--;
else if ( if_level)
if_level--;
}
if ( ! if_skip)
display_server_var( server, var);
t+= varlen;
}
}
void
template_display_players( struct qserver *server)
{
struct player *player;
for ( player= server->players; player != NULL; player= player->next)
template_display_player( server, player);
}
void
template_display_player( struct qserver *server, struct player *player)
{
char *t= player_template;
int var, varlen;
if ( player_template == NULL)
return;
if_level= 0;
if_skip= 0;
for ( ; *t; t++) {
if ( *t != VARIABLE_CHAR) {
if ( ! if_skip)
putc( *t, OF);
continue;
}
var= parse_var( t, &varlen);
if ( var == -1) {
if ( ! if_skip)
putc( VARIABLE_CHAR, OF);
continue;
}
if ( var == V_BACKSLASH) {
t+= 2;
if ( *t == '\r') {
if ( *++t == '\n')
t++;
}
else if ( *t == '\n')
t++;
t--;
continue;
}
if ( (var == V_IF || var == V_IFNOT) && variable_option != NULL) {
int truth= (var==V_IF)?1:0;
if ( !if_skip && is_true( server, player, NULL, variable_option) == truth)
if_level++;
else
if_skip++;
}
else if ( var == V_ENDIF) {
if ( if_skip)
if_skip--;
else if ( if_level)
if_level--;
}
if ( ! if_skip)
display_player_var( player, var, server);
t+= varlen;
}
}
void
template_display_rules( struct qserver *server)
{
struct rule *rule;
for ( rule= server->rules; rule != NULL; rule= rule->next)
template_display_rule( server, rule);
}
void
template_display_rule( struct qserver *server, struct rule *rule)
{
char *t= rule_template;
int var, varlen;
if ( rule_template == NULL)
return;
if_level= 0;
if_skip= 0;
for ( ; *t; t++) {
if ( *t != VARIABLE_CHAR) {
if ( ! if_skip)
putc( *t, OF);
continue;
}
var= parse_var( t, &varlen);
if ( var == -1) {
if ( ! if_skip)
putc( VARIABLE_CHAR, OF);
continue;
}
if ( var == V_BACKSLASH) {
t+= 2;
if ( *t == '\r') {
if ( *++t == '\n')
t++;
}
else if ( *t == '\n')
t++;
t--;
continue;
}
if ( (var == V_IF || var == V_IFNOT) && variable_option != NULL) {
int truth= (var==V_IF)?1:0;
if ( !if_skip && is_true( server, NULL, rule, variable_option) == truth)
if_level++;
else
if_skip++;
}
else if ( var == V_ENDIF) {
if ( if_skip)
if_skip--;
else if ( if_level)
if_level--;
}
if ( ! if_skip)
display_rule_var( rule, var, server);
t+= varlen;
}
}
void
template_display_header()
{
char *t= header_template;
int var, varlen;
if_level= 0;
if_skip= 0;
for ( ; *t; t++) {
if ( *t != VARIABLE_CHAR) {
putc( *t, OF);
continue;
}
var= parse_var( t, &varlen);
if ( var == -1) {
putc( VARIABLE_CHAR, OF);
continue;
}
if ( var == V_BACKSLASH) {
t+= 2;
if ( *t == '\r') {
if ( *++t == '\n')
t++;
}
else if ( *t == '\n')
t++;
t--;
continue;
}
display_generic_var( var);
t+= varlen;
}
}
void
template_display_trailer()
{
char *t= trailer_template;
int var, varlen;
if_level= 0;
if_skip= 0;
for ( ; *t; t++) {
if ( *t != VARIABLE_CHAR) {
putc( *t, OF);
continue;
}
var= parse_var( t, &varlen);
if ( var == -1) {
putc( VARIABLE_CHAR, OF);
continue;
}
if ( var == V_BACKSLASH) {
t+= 2;
if ( *t == '\r') {
if ( *++t == '\n')
t++;
}
else if ( *t == '\n')
t++;
t--;
continue;
}
display_generic_var( var);
t+= varlen;
}
}
STATIC void
display_server_var( struct qserver *server, int var)
{
char *game;
int full_data= 1;
if ( server->server_name == DOWN || server->server_name == TIMEOUT ||
server->server_name == SYSERROR ||
server->error != NULL || server->type->master)
full_data= 0;
switch( var) {
case V_HOSTNAME:
fputs( (hostname_lookup) ? server->host_name : server->arg, OF);
break;
case V_SERVERNAME:
fputs( xform_name( server->server_name, server), OF);
break;
case V_PING:
if ( server->server_name != TIMEOUT && server->server_name != DOWN &&
server->server_name != HOSTNOTFOUND)
fprintf( OF, "%d", server->ping_total/server->n_requests);
break;
case V_PLAYERS:
if ( full_data)
fprintf( OF, "%d", server->num_players);
break;
case V_MAXPLAYERS:
if ( full_data)
fprintf( OF, "%d", server->max_players);
break;
case V_MAP:
if ( full_data)
fputs( (server->map_name) ? server->map_name : "?", OF);
break;
case V_GAME:
if ( full_data) {
game= get_qw_game( server);
fputs( (game) ? game : "", OF);
}
break;
case V_GAMETYPE:
{
struct rule *rule;
for ( rule= server->rules; rule != NULL; rule= rule->next)
if ( strcasecmp( rule->name, "g_gametype") == 0)
break;
if ( rule != NULL) {
switch ( atoi(rule->value)) {
case 0: fputs( "Free For All", OF); break;
case 1: fputs( "Tournament", OF); break;
case 3: fputs( "Team Deathmatch", OF); break;
case 4: fputs( "Capture the Flag", OF); break;
case 5: fputs( "Fortress or OSP", OF); break;
case 6: fputs( "Capture and Hold", OF); break;
case 8: fputs( "Arena", OF); break;
default: fputs( "?", OF); break;
}
}
}
break;
case V_RETRIES:
if ( server->server_name != TIMEOUT && server->server_name != DOWN &&
server->server_name != HOSTNOTFOUND)
fprintf( OF, "%d", server->n_retries);
break;
case V_IPADDR:
{ unsigned int ipaddr= ntohl(server->ipaddr);
fprintf( OF, "%u.%u.%u.%u", (ipaddr>>24)&0xff,
(ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff);
}
break;
case V_PORT:
fprintf( OF, "%hu", server->port);
break;
case V_ARG:
fputs( server->arg, OF);
break;
case V_TYPE:
fputs( server->type->game_name, OF);
break;
case V_TYPESTRING:
fputs( server->type->type_string, OF);
break;
case V_TYPEPREFIX:
fputs( server->type->type_prefix, OF);
break;
case V_RULE:
{
struct rule *rule;
if ( variable_option == NULL)
break;
for ( rule= server->rules; rule != NULL; rule= rule->next)
if ( strcasecmp( rule->name, variable_option) == 0)
display_string( rule->value);
}
break;
case V_ALLRULES:
{
struct rule *rule;
for ( rule= server->rules; rule != NULL; rule= rule->next) {
if ( rule != server->rules)
fputs( ", ", OF);
display_string( rule->name);
putc( '=', OF);
display_string( rule->value);
}
}
break;
case V_PLAYERTEMPLATE:
if_level_save= if_level;
if_skip_save= if_skip;
template_display_players( server);
if_level= if_level_save;
if_skip= if_skip_save;
break;
case V_RULETEMPLATE:
if_level_save= if_level;
if_skip_save= if_skip;
template_display_rules( server);
if_level= if_level_save;
if_skip= if_skip_save;
break;
default:
display_generic_var( var);
}
}
STATIC void
display_player_var( struct player *player, int var, struct qserver *server)
{
switch( var) {
case V_PLAYERNAME:
fputs( xform_name( player->name, server), OF);
break;
case V_HTMLPLAYERNAME: {
int save_html_names= html_names;
int save_hex_player_names= hex_player_names;
html_names= 1;
hex_player_names= 0;
fputs( xform_name( player->name, server), OF);
html_names= save_html_names;
hex_player_names= save_hex_player_names;
}
break;
case V_TRIBETAG:
fputs( xform_name( player->tribe_tag, server), OF);
break;
case V_FRAGS:
fprintf( OF, "%d", player->frags);
break;
case V_DEATHS:
fprintf( OF, "%d", player->deaths);
break;
case V_PLAYERPING:
fprintf( OF, "%d", player->ping);
break;
case V_CONNECTTIME:
fputs( play_time(player->connect_time,0), OF);
break;
case V_SKIN:
display_string( player->skin);
break;
case V_MESH:
display_string( player->mesh);
break;
case V_FACE:
display_string( player->face);
break;
case V_SHIRTCOLOR:
if ( color_names)
fputs( quake_color(player->shirt_color), OF);
else
fprintf( OF, "%d", player->shirt_color);
break;
case V_PANTSCOLOR:
if ( color_names)
fputs( quake_color(player->pants_color), OF);
else
fprintf( OF, "%d", player->pants_color);
break;
case V_PLAYERIP:
if ( player->address)
fputs( player->address, OF);
break;
case V_TEAMNUM:
fprintf( OF, "%d", player->team);
break;
case V_PACKETLOSS:
fprintf( OF, "%d", player->packet_loss);
break;
case V_TEAMNAME:
if ( player->team_name)
fprintf( OF, "%s", player->team_name);
break;
case V_COLORNUMBERS:
color_names= 0;
break;
case V_COLORNAMES:
color_names= 1;
break;
case V_COLORRGB:
color_names= 2;
break;
case V_TIMESECONDS:
time_format= SECONDS;
break;
case V_TIMECLOCK:
time_format= CLOCK_TIME;
break;
case V_TIMESTOPWATCH:
time_format= STOPWATCH_TIME;
break;
default:
display_server_var( server, var);
}
}
STATIC void
display_rule_var( struct rule *rule, int var, struct qserver *server)
{
switch( var) {
case V_RULENAME:
fputs( rule->name, OF);
break;
case V_RULEVALUE:
fputs( xform_name( rule->value, server), OF);
break;
default:
display_server_var( server, var);
}
}
STATIC void
display_generic_var( int var)
{
switch( var) {
case V_QSTATURL:
fputs( "http://www.qstat.org", OF);
break;
case V_QSTATVERSION:
fputs( qstat_version, OF);
break;
case V_QSTATAUTHOR:
fputs( "Steve Jankowski", OF);
break;
case V_QSTATAUTHOREMAIL:
fputs( "steve@qstat.org", OF);
break;
case V_HTML:
html_mode^= 1;
if ( html_mode && html_names == -1)
html_names= 1;
break;
case V_CLEARNEWLINES:
clear_newlines_mode^= 1;
break;
case V_NOW: {
time_t now= time(0);
char *now_string= ctime(&now);
now_string[strlen(now_string)-1]= '\0';
fputs( now_string, OF);
break;
}
case V_NOWINT:
fprintf( OF, "%u", (unsigned int)time(0));
break;
case V_TOTALSERVERS:
fprintf( OF, "%d", num_servers_total);
break;
case V_TOTALUP:
fprintf( OF, "%d", num_servers_total - num_servers_timed_out -
num_servers_down);
break;
case V_TOTALNOTUP:
fprintf( OF, "%d", num_servers_timed_out + num_servers_down);
break;
case V_TOTALPLAYERS:
fprintf( OF, "%d", num_players_total);
break;
case V_DEFAULTTYPE:
fprintf( OF, "%s", default_server_type->game_name);
break;
case V_RULENAMESPACES:
rule_name_spaces^= 1;
break;
default: break;
}
}
STATIC int
parse_var( char *varname, int *varlen)
{
char *v= ++varname, *colon= NULL;
int i, quote= 0;
if ( variable_option != NULL) {
free( variable_option);
variable_option= NULL;
}
if ( *v == '(') {
v++;
varname++;
quote++;
}
else if ( *v == '\\') {
*varlen= 1;
return V_BACKSLASH;
}
for ( ; *v; v++)
if ( (!quote && !isalpha( *v)) || (quote && (*v == ')' || *v == ':')))
break;
if ( v-varname == 0)
return -1;
*varlen= v-varname;
if ( *v == ':')
colon= v;
else if ( quote && *v == ')')
v++;
for ( i= 0; i < sizeof(variable_defs)/sizeof(struct vardef); i++)
if ( strncasecmp( varname, variable_defs[i].var, *varlen) == 0 &&
*varlen == strlen(variable_defs[i].var)) {
if ( colon != NULL && ((variable_defs[i].options & OPTIONS_OK) || quote)) {
for ( v++; *v; v++) {
if ( (!quote && !isalnum( *v) && *v != '*' && *v != '_' && *v != '.' && (*v == ' ' && !rule_name_spaces)) ||
(quote==1 && *v == ')')) break;
if ( *v == '(')
quote++;
else if ( *v == ')')
quote--;
}
variable_option= (char*)malloc( v-colon+1);
strncpy( variable_option, colon+1, v-colon-1);
variable_option[v-colon-1]= '\0';
if ( quote && *v == ')')
v++;
}
*varlen= v-varname+quote;
return variable_defs[i].varcode;
}
return -1;
}
STATIC int
is_true( struct qserver *server, struct player *player, struct rule *rule,
char *expr)
{
int i, len, arglen;
char *arg= NULL, *lparen, *rparen;
server_type *t;
if ( (lparen= strchr( expr, '(')) != NULL) {
if ( (rparen= strchr( lparen, ')')) != NULL) {
len= lparen - expr;
arg= lparen + 1;
arglen= rparen - lparen - 1;
}
}
else
len= strlen( expr);
for ( i= 0; i < sizeof(variable_defs)/sizeof(struct vardef); i++)
if ( strncasecmp( expr, variable_defs[i].var, len) == 0 &&
len == strlen( variable_defs[i].var)) {
if ( !(variable_defs[i].options & EXPR)) {
fprintf( stderr, "unsupported IF expression \"%s\"\n", expr);
return 1;
}
switch ( variable_defs[i].varcode) {
case V_GAME: {
char *g= get_qw_game( server);
if ( g == NULL || *g == '\0')
return 0;
else
return 1;
}
case V_PLAYERS: return server->num_players > 0;
case V_ISEMPTY: return server->num_players == 0;
case V_ISFULL: return server->max_players ? server->num_players >= server->max_players : 0;
case V_ISTEAM: return player ? player->number == TRIBES_TEAM : 0;
case V_ISBOT: return player ? player->type_flag == PLAYER_TYPE_BOT : 0;
case V_ISALIAS: return player ? player->type_flag == PLAYER_TYPE_ALIAS : 0;
case V_TRIBETAG: return player ? player->tribe_tag != NULL : 0;
case V_RULE: {
struct rule *rule;
if ( arg == NULL)
return 0;
for ( rule= server->rules; rule != NULL; rule= rule->next)
if ( strncasecmp( rule->name, arg, arglen) == 0 &&
strlen( rule->name) == arglen)
return 1;
return 0;
}
case V_RULENAME: {
if ( rule && arg && strncmp( rule->name, arg, arglen) == 0 &&
strlen( rule->name) == arglen)
return 1;
else
return 0;
}
case V_RULEVALUE: {
if ( rule && arg && strncmp( rule->value, arg, arglen) == 0 &&
strlen( rule->value) == arglen)
return 1;
else
return 0;
}
case V_FLAG: {
if ( strncmp( "-H", arg, arglen) == 0)
return hostname_lookup;
if ( strncmp( "-P", arg, arglen) == 0)
return get_player_info;
if ( strncmp( "-R", arg, arglen) == 0)
return get_server_rules;
return 0;
}
case V_UP:
return server->server_name != DOWN &&
server->server_name != TIMEOUT &&
server->server_name != HOSTNOTFOUND;
case V_DOWN:
return server->server_name == DOWN;
case V_TIMEOUT:
return server->server_name == TIMEOUT;
case V_HOSTNOTFOUND:
return server->server_name == HOSTNOTFOUND;
case V_ISMASTER:
return (server->type->id & MASTER_SERVER) ? 1 : 0;
default: return 0;
}
}
t= &types[0];
for ( ; t->id; t++)
if ( strncasecmp( expr, t->template_var, len) == 0)
return server->type->id == t->id;
fprintf( stderr, "bad IF expression \"%s\"\n", expr);
return 0;
}
STATIC void
display_string( char *str)
{
if ( str == NULL)
return;
if ( ! html_mode && ! clear_newlines_mode) {
fputs( str, OF);
return;
}
if ( html_mode && ! clear_newlines_mode) {
for ( ; *str; str++)
switch ( *str) {
case '<': fputs( "<", OF); break;
case '>': fputs( ">", OF); break;
case '&': fputs( "&", OF); break;
case '\n': fputs( "NEWLINE", OF);
default: putc( *str, OF);
}
return;
}
if ( ! html_mode && clear_newlines_mode) {
for ( ; *str; str++)
switch ( *str) {
case '\n':
case '\r': putc( ' ', OF); break;
default: putc( *str, OF);
}
return;
}
for ( ; *str; str++)
switch ( *str) {
case '<': fputs( "<", OF); break;
case '>': fputs( ">", OF); break;
case '&': fputs( "&", OF); break;
case '\n':
case '\r': putc( ' ', OF); break;
default: putc( *str, OF);
}
}